// These are meant to be typed into the REPL. You can also run
// scala -Xnojline < repl-session.scala to run them all at once.
/**
  * 7.6 嵌套类
  * 在 Scala 中， 你几乎可以在任何语法结构中嵌套任何语法结构， 在函数
  * 中定义函数， 在类中定义类。 Java 中的内部类从属于外部类。 Scala 中每一个
  * 实例都有一个内部类，内部类从属于实例。
  */

import scala.collection.mutable.ArrayBuffer

class Network {
  class Member(val name: String) {
    val contacts = new ArrayBuffer[Member]
  }

  private val members = new ArrayBuffer[Member]

  def join(name: String) = {
    val m = new Member(name)
    members += m
    m
  }
}

val chatter = new Network
val myFace = new Network

val fred = chatter.join("Fred")
val wilma = chatter.join("Wilma")
fred.contacts += wilma // OK
val barney = myFace.join("Barney") // Has type myFace.Member
fred.contacts += barney // No
  // Can’t add a myFace.Member to a buffer of chatter.Member elements
/**
  * 在 Scala 中， 每个实例都有它自己的 Member 类， 就和他们有自己的
  * members 字段一样。 也就是说， chatter.Member 和 myFace.Member 是不同的
  * 两个类。
  * 创建新的内部对象： new chatter.Member
  * 如果想让 members 接受所有实例的 Member， 一般有两种办法
  * 1、 将 Member 作为 Network 的伴生对象存在：
  * class Network {
  * private val members = new ArrayBuffer[Network.Member]
  * def join(name: String) = {
  * val m = new Network.Member(name)
  * members += m
  * m
  * }
  * def description = "a network with members " +
  * (for (m <- members) yield m.description).mkString(", ")
  * }
  * object Network {
  * class Member(val name: String) {
  * val contacts = new ArrayBuffer[Member]
  * def description = name + " with contacts " +
  * (for (c <- contacts) yield c.name).mkString(" ")
  * }
  * }
  *
  * 2、 你可以使用类型投影， Network#Member ： 任何 Network 的 Member
  * class Network {
  * class Member(val name: String) {
  * val contacts = new ArrayBuffer[Network#Member]
  * }
  * private val members = new ArrayBuffer[Member]
  * def join(name: String) = {
  * val m = new Member(name)
  * members += m
  * m
  * }
  * }
  * 注意：在内嵌类中，你可以通过 外部类.this 的方式来访问外部类的 this 引用。
  * 还可以对其进行命名访问。
  */
class Network1 {
  class Member(val name: String) {
    val contacts = new ArrayBuffer[Network1#Member]
  }

  private val members = new ArrayBuffer[Member]

  def join(name: String) = {
    val m = new Member(name)
    members += m
    m
  }
}

val chatter1 = new Network1
val myFace1 = new Network1

val fred1 = chatter1.join("Fred")
val wilma1 = chatter1.join("Wilma")
fred1.contacts += wilma1 // OK
val barney1 = myFace1.join("Barney")
fred1.contacts += barney1 // Also OK




//class Network {
//  private val members = new ArrayBuffer[Network.Member]
//  def join(name: String) = {
//    val m = new Network.Member(name)
//    members += m
//    m
//  }
//  def description = "a network with members " +
//      (for (m <- members) yield m.description).mkString(", ")
//}
//object Network {
//  class Member(val name: String) {
//    val contacts = new ArrayBuffer[Member]
//    def description = name + " with contacts " +
//        (for (c <- contacts) yield c.name).mkString(" ")
//  }
//}
////2、 你可以使用类型投影， Network#Member ： 任何 Network 的 Member
//class Network {
//  class Member(val name: String) {
//    val contacts = new ArrayBuffer[Network#Member]
//  }
//  private val members = new ArrayBuffer[Member]
//  def join(name: String) = {
//    val m = new Member(name)
//    members += m
//    m
//  }
//}
//注意：在内嵌类中，你可以通过 外部类.this 的方式来访问外部类的 this 引用。
//还可以对其进行命名访问。
